import sys
import os
# 获取当前文件所在目录的父目录（即项目根目录）
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if project_root not in sys.path:
    sys.path.append(project_root)
import asyncio
import logging
from contextlib import asynccontextmanager
import re
import os
import queue
import random
import time
from datetime import datetime
from common import feishu_api
import yaml
import requests
import json
import threading
from logging.handlers import TimedRotatingFileHandler
from common.feishu_api import get_app_token, sendToFeishu, get_date
from common.oss import OSSManager,get_token
from common.redis_util import set_proxies, get_proxies, get_lock, release_lock, delete_lock, get_trino_lock


INSERT_TRINO_LOCK = threading.Lock()

# 创建日志目录
LOG_DIR = "./data/bilibili-scrawler/logs"

os.makedirs(LOG_DIR, exist_ok=True)

# 全局变量存储代理IP列表
proxy_list = []
proxy_lock = threading.Lock()  # 用于线程安全

# 代理黑名单 - 存储最近失败的代理IP
proxy_blacklist = set()
blacklist_lock = threading.Lock()  # 用于线程安全访问黑名单
BLACKLIST_TIMEOUT = (1 * 60)  # 黑名单超时时间（秒）

# 代理API配置
PROXY_API_URL = "http://api.shenlongip.com/ip"
PROXY_API_PARAMS = {
    "key": "0k84pwav",
    "pattern": "json",
    "count": 15,
    "need": 1100,
    "mr": 1,
    "protocol": 1,
    "sign": "8c816d4b41a00af3450de7f30064ccad"
}
PROXY_API_PARAMS_KS = {
    "key": "0k84pwav",
    "pattern": "json",
    "count": 10,
    "need": 1100,
    "mr": 1,
    "protocol": 1,
    "sign": "8c816d4b41a00af3450de7f30064ccad"
}
PROXY_UPDATE_INTERVAL = 5 * 60

VIDEO_RESPONSE_TIME_SUM = 0.0
TAG_RESPONSE_TIME_SUM = 0.0

# 配置日志
def setup_logging():
    """
    设置日志配置，包括控制台输出和按天轮转的文件日志
    """
    # 根日志记录器（默认）
    root_logger = logging.getLogger()
    root_logger.setLevel(logging.INFO)

    # Bilibili 专用 Logger
    bilibili_logger = logging.getLogger("bilibili")
    bilibili_logger.setLevel(logging.INFO)

    # Douyin 专用 Logger
    douyin_logger = logging.getLogger("douyin")
    douyin_logger.setLevel(logging.INFO)

    # Kuaishou 专用 Logger
    kuaishou_logger = logging.getLogger("kuaishou")
    kuaishou_logger.setLevel(logging.INFO)

    # Xiaohongshu 专用 Logger
    xiaohongshu_logger = logging.getLogger("xiaohongshu")
    xiaohongshu_logger.setLevel(logging.INFO)

    # 标准格式化器（用于控制台输出）
    std_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')

    # 控制台处理器（默认）
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(std_formatter)
    root_logger.addHandler(console_handler)

    # Bilibili 的 Handler 和 Formatter
    bilibili_formatter = logging.Formatter('%(asctime)s - [BILIBILI] - %(levelname)s - %(message)s')
    bilibili_handler = logging.StreamHandler()
    bilibili_handler.setFormatter(bilibili_formatter)
    bilibili_logger.addHandler(bilibili_handler)
    bilibili_logger.propagate = False  # 阻止向上传播到 root_logger

    # Douyin 的 Handler 和 Formatter
    douyin_formatter = logging.Formatter('%(asctime)s - [DOUYIN] - %(levelname)s - %(message)s')
    douyin_handler = logging.StreamHandler()
    douyin_handler.setFormatter(douyin_formatter)
    douyin_logger.addHandler(douyin_handler)
    douyin_logger.propagate = False  # 阻止向上传播到 root_logger

    # Kuaishou 的 Handler 和 Formatter
    kuaishou_formatter = logging.Formatter('%(asctime)s - [KUAISHOU] - %(levelname)s - %(message)s')
    kuaishou_handler = logging.StreamHandler()
    kuaishou_handler.setFormatter(kuaishou_formatter)
    kuaishou_logger.addHandler(kuaishou_handler)
    kuaishou_logger.propagate = False  # 阻止向上传播到 root_logger

    # Xiaohongshu 的 Handler 和 Formatter
    xiaohongshu_formatter = logging.Formatter('%(asctime)s - [XIAOHONGSHU] - %(levelname)s - %(message)s')
    xiaohongshu_handler = logging.StreamHandler()
    xiaohongshu_handler.setFormatter(xiaohongshu_formatter)
    xiaohongshu_logger.addHandler(xiaohongshu_handler)
    xiaohongshu_logger.propagate = False  # 阻止向上传播到 root_logger

    return root_logger,bilibili_logger,douyin_logger,kuaishou_logger,xiaohongshu_logger


# 初始化日志
logger,bilibili_logger,douyin_logger,kuaishou_logger,xiaohongshu_logger = setup_logging()

# 配置文件路径
CONFIG_FILE = "./common/config.yaml"

# 评论文件名模板
COMMENTS_FILE_TEMPLATE = "videos_{}.json"



def load_config():
    """
    从YAML配置文件加载配置

    Returns:
        dict: 配置字典
    """
    try:
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            config = yaml.safe_load(f)
        logger.info(f"成功加载配置文件: {CONFIG_FILE}")
        return config
    except Exception as e:
        print(e)
        logger.error(f"加载配置文件失败: {e}")
        logger.error(f"请确保 {CONFIG_FILE} 文件存在且格式正确")
        # 直接退出程序
        import sys
        sys.exit(1)

config = load_config()

def get_videos_filename(mid):
    """
    获取指定up主的视频信息文件名

    Args:
         mid (str): up主uid

    Returns:
        str: 视频信息文件名
    """
    return COMMENTS_FILE_TEMPLATE.format(mid)

ALL_PROXY_IP = []


def fetch_proxy_list_ks():
    """
    从API获取代理IP列表

    Returns:
        list: 代理IP列表，格式为 [{'ip': '1.2.3.4', 'port': 8080, 'expire': '2025-03-18 12:00:39'}, ...]
    """

    logger.info("正在获取IP代理锁...")
    ok,id = get_lock("bilibili_scrawler:proxy_list")

    if ok == False:
        logger.error("获取IP代理锁失败")
        time.sleep(5)
        return []

    logger.info("获取IP代理锁成功")

    try:
        logger.info("正在获取代理IP列表...")
        response = requests.get(PROXY_API_URL, params=PROXY_API_PARAMS_KS)

        if response.status_code != 200:
            logger.error(f"获取代理IP失败，状态码: {response.status_code}")
            logger.error(f"响应内容: {response.text[:200]}")
            return []

        # API返回的content-type是text/plain，需要手动解析JSON
        try:
            data = json.loads(response.text)
            if data.get("code") == 200 and "data" in data:
                proxies = data["data"]
                ALL_PROXY_IP.append(proxies)
                logger.info(f"成功获取 {len(proxies)} 个代理IP")
                logger.info(f"代理IP列表: {proxies}")
                # 更新全局代理列表
                set_proxies(proxies)

                return proxies
            else:
                logger.error(f"代理API返回非成功状态: {data}")
                return []
        except json.JSONDecodeError:
            logger.error(f"解析代理API响应失败: {response.text[:200]}")
            return []
    except Exception as e:
        logger.error(f"获取代理IP时出错: {e}")
        return []

def fetch_proxy_list():
    """
    从API获取代理IP列表

    Returns:
        list: 代理IP列表，格式为 [{'ip': '1.2.3.4', 'port': 8080, 'expire': '2025-03-18 12:00:39'}, ...]
    """

    logger.info("正在获取IP代理锁...")
    ok,id = get_lock("bilibili_scrawler:proxy_list")

    if ok == False:
        logger.error("获取IP代理锁失败")
        time.sleep(5)
        return []

    logger.info("获取IP代理锁成功")

    try:
        logger.info("正在获取代理IP列表...")
        response = requests.get(PROXY_API_URL, params=PROXY_API_PARAMS)

        if response.status_code != 200:
            logger.error(f"获取代理IP失败，状态码: {response.status_code}")
            logger.error(f"响应内容: {response.text[:200]}")
            return []

        # API返回的content-type是text/plain，需要手动解析JSON
        try:
            data = json.loads(response.text)
            if data.get("code") == 200 and "data" in data:
                proxies = data["data"]
                ALL_PROXY_IP.append(proxies)
                logger.info(f"成功获取 {len(proxies)} 个代理IP")
                logger.info(f"代理IP列表: {proxies}")
                # 更新全局代理列表
                set_proxies(proxies)

                return proxies
            else:
                logger.error(f"代理API返回非成功状态: {data}")
                return []
        except json.JSONDecodeError:
            logger.error(f"解析代理API响应失败: {response.text[:200]}")
            return []
    except Exception as e:
        logger.error(f"获取代理IP时出错: {e}")
        return []
    # finally:
    #     release_lock("bilibili_scrawler:proxy_list",id)

STOP_EVENT = threading.Event()


def get_random_proxy():
    proxies = get_proxies()

    if not proxies:
        logger.info("缓存未找到IP池，尝试更新 ...")
        fetch_proxy_list()
        proxies = get_proxies()

    # 过滤掉黑名单中的代理
    available_proxies = [p for p in proxies if p['ip'] not in proxy_blacklist]

    if len(available_proxies) == 0:
        logger.info("IP池无可用IP，尝试更新 ...")
        fetch_proxy_list()
        proxies = get_proxies()
        return random.choice(proxies)

    return random.choice(available_proxies)

def get_random_proxy_ks():
    proxies = get_proxies()

    if not proxies:
        logger.info("缓存未找到IP池，尝试更新 ...")
        fetch_proxy_list_ks()
        proxies = get_proxies()

    # 过滤掉黑名单中的代理
    available_proxies = [p for p in proxies if p['ip'] not in proxy_blacklist]

    if len(available_proxies) == 0:
        logger.info("IP池无可用IP，尝试更新 ...")
        fetch_proxy_list_ks()
        proxies = get_proxies()
        return random.choice(proxies)

    return random.choice(available_proxies)


def add_proxy_to_blacklist(ip):
    """
    将代理IP添加到黑名单

    Args:
        ip (str): 代理服务器IP地址
    """
    with blacklist_lock:
        proxy_blacklist.add(ip)
    logger.warning(f"代理IP {ip} 添加到黑名单")

    # 创建定时任务，在一段时间后从黑名单中移除
    def remove_from_blacklist():
        time.sleep(BLACKLIST_TIMEOUT)
        with blacklist_lock:
            if ip in proxy_blacklist:
                proxy_blacklist.remove(ip)
                logger.info(f"代理IP {ip} 已从黑名单中移除")

    # 启动后台线程处理黑名单超时
    threading.Thread(target=remove_from_blacklist, daemon=True).start()


def get_wx_from_text(text):
    wx_pattern = r'(?i)(?:wx|vx|v|微信|微)\s*[:：]\s*([a-zA-Z][a-zA-Z0-9_-]{5,19})'
    matches = re.findall(wx_pattern, text)
    if matches:
        return matches[0]
    else:
        return ""



THIS_REQUEST_TIME = str(datetime.now().date()) + "-" +str(int(time.time()))

THIS_UPDATE_TIME = str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
